
# ifndef __DFX_PROGRAM_H__
# define __DFX_PROGRAM_H__

# include "dfxCore.h"
# include "dfxStream.h"
# include "dfxVertexFormat.h"

# include "dfxVector2.h"
# include "dfxVector3.h"
# include "dfxVector4.h"
# include "dfxTexture.h"

namespace DFX
{
    class GraphicsDevice;

    enum SHADER_TYPE
    {
        SHADER_TYPE_VERTEX,
        SHADER_TYPE_GEOMETRY,
        SHADER_TYPE_FRAGMENT,
        SHADER_TYPE_MAX
    };

    class DFX_EXPORT Program
    {
    protected:

        String              mName;
        GraphicsDevice     *mGraphicsDevice;

    public:

        Program(GraphicsDevice *gd, const String &name)
            : mGraphicsDevice(gd), mName(name)
        {
        }

        virtual ~Program()
        {
        }

        const String& GetName() const
        {
            return mName;
        }

        GraphicsDevice* GetGraphicsDevice() const
        {
            return mGraphicsDevice;
        }

        virtual DFXRESULT LoadShader(SHADER_TYPE shaderType, InputStream *stream) = 0; 
        virtual DFXRESULT Link() = 0;
        virtual DFXRESULT Destroy() = 0;

        virtual void Bind() = 0;
        virtual void BindVertexFormat(VertexFormat *format) = 0;

        virtual UInt32 GetConstantLocation(const String &name) = 0;

        virtual void SetVector2(UInt32 loc, const Vector2 &v) = 0;
        virtual void SetVector3(UInt32 loc, const Vector3 &v) = 0;
        virtual void SetVector4(UInt32 loc, const Vector4 &v) = 0;

        virtual void SetVector2(UInt32 loc, Float32 x, Float32 y) = 0;
        virtual void SetVector3(UInt32 loc, Float32 x, Float32 y, Float32 z) = 0;
        virtual void SetVector4(UInt32 loc, Float32 x, Float32 y, Float32 z, Float32 w) = 0;

        virtual void SetFloat(UInt32 loc, Float32 v) = 0;
        virtual void SetTexture(UInt32 loc, UInt32 unit, Texture *t) = 0;

        virtual void SetVector2(const String &name, const Vector2 &v) = 0;
        virtual void SetVector3(const String &name, const Vector3 &v) = 0;
        virtual void SetVector4(const String &name, const Vector4 &v) = 0;
        
        virtual void SetVector2(const String &name, Float32 x, Float32 y) = 0;
        virtual void SetVector3(const String &name, Float32 x, Float32 y, Float32 z) = 0;
        virtual void SetVector4(const String &name, Float32 x, Float32 y, Float32 z, Float32 w) = 0;

        virtual void SetFloat(const String &name, Float32 v) = 0;
        virtual void SetTexture(const String &name, UInt32 unit, Texture *t) = 0;
    };
}

# endif